package org.xiaojl.config.quartz.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.xiaojl.common.Constants;
import org.xiaojl.config.quartz.ScheduleJobFactory;
import org.xiaojl.config.quartz.ScheduleJobFactoryNotCurrent;
import org.xiaojl.config.quartz.service.TaskJobManageService;
import org.xiaojl.modules.task.entity.TaskJob;
import org.xiaojl.modules.task.service.TaskJobService;
import org.xiaojl.utils.ToolUtil;

import com.baomidou.mybatisplus.mapper.EntityWrapper;

@Service("taskJobManageService")
public class TaskJobManagerServiceImpl implements TaskJobManageService{
	public final Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private SchedulerFactoryBean schedulerFactoryBean;
	@Autowired
	private TaskJobService taskJobService;
	
	@Override
	public void addTaskJob(TaskJob taskJob) {
		if(ToolUtil.isEmpty(taskJob) 
				|| Constants.JOB_STATUS_NOT_RUNNING.equals(taskJob.getJobStatus())){
			return ;
		}
		
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		logger.info("开始添加任务，任务:" + taskJob.getJobName());
		try {
			TriggerKey key = TriggerKey.triggerKey(taskJob.getJobName(), taskJob.getJobGroup());
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(key);
			if(trigger == null){
				Class clz = Constants.JOB_CONCURRENT_IS.equals(taskJob.getIsConcurrent())?ScheduleJobFactory.class:ScheduleJobFactoryNotCurrent.class;
				JobDetail jobDetail = JobBuilder.newJob(clz).withIdentity(taskJob.getJobName(), taskJob.getJobGroup()).build();
				jobDetail.getJobDataMap().put("taskJob", taskJob);
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(taskJob.getCron());
				trigger = TriggerBuilder.newTrigger()
							.withIdentity(taskJob.getJobName(), taskJob.getJobGroup())
							.withSchedule(scheduleBuilder).build();
				scheduler.scheduleJob(jobDetail, trigger);
				
			}else{
				// Trigger已存在，那么更新相应的定时设置
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(taskJob.getCron());
				// 按新的cronExpression表达式重新构建trigger
				trigger = trigger.getTriggerBuilder().withIdentity(key).withSchedule(scheduleBuilder).build();
				// 按新的trigger重新设置job执行
				scheduler.rescheduleJob(key, trigger);
			}
			
		} catch (Exception e) {
			logger.error("添加任务出错，任务:" + taskJob.getJobName());
		}
		logger.info("添加任务完成，任务:" + taskJob.getJobName());
		
	}

	@Override
	public void pauseTaskJob(TaskJob taskJob) {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			JobKey jobKey = JobKey.jobKey(taskJob.getJobName(), taskJob.getJobGroup());
			scheduler.pauseJob(jobKey);
		} catch (Exception e) {
			logger.error("暂停任务出错，任务:" + taskJob.getJobName());
			throw new RuntimeException("暂停任务出错，任务:" + taskJob.getJobName(),e);
		}
	}

	@Override
	public void resumeTaskJob(TaskJob taskJob) {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			JobKey jobKey = JobKey.jobKey(taskJob.getJobName(), taskJob.getJobGroup());
			scheduler.resumeJob(jobKey);
		} catch (Exception e) {
			logger.error("恢复任务出错，任务:" + taskJob.getJobName());
			throw new RuntimeException("恢复任务出错，任务:" + taskJob.getJobName(), e);
		}
	}

	@Override
	public void deleteTaskJob(TaskJob taskJob) {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			JobKey jobKey = JobKey.jobKey(taskJob.getJobName(), taskJob.getJobGroup());
			scheduler.deleteJob(jobKey);
		} catch (Exception e) {
			logger.error("删除任务出错，任务:" + taskJob.getJobName());
			throw new RuntimeException("删除任务出错，任务:" + taskJob.getJobName(), e);
		}
	}

	@Override
	public void runTaskJobNow(TaskJob taskJob) {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			JobKey jobKey = JobKey.jobKey(taskJob.getJobName(), taskJob.getJobGroup());
			scheduler.triggerJob(jobKey);
		} catch (Exception e) {
			logger.error("立即启动任务出错，任务:" + taskJob.getJobName());
			throw new RuntimeException("立即启动任务出错，任务:" + taskJob.getJobName(), e);
		}
	}

	@Override
	public void updateSchedule(TaskJob taskJob) {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(taskJob.getJobName(), taskJob.getJobGroup());
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(taskJob.getCron());
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			scheduler.rescheduleJob(triggerKey, trigger);
		} catch (Exception e) {
			logger.error("更新任务出错，任务:" + taskJob.getJobName());
			throw new RuntimeException("更新任务出错，任务:" + taskJob.getJobName(), e);
		}
	}

	@Override
	public List<TaskJob> getAllTaskJob() {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
			Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
			List<TaskJob> jobList = new ArrayList<TaskJob>();
			for (JobKey jobKey : jobKeys) {
				List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
				for (Trigger trigger : triggers) {
					TaskJob job = new TaskJob();
					job.setJobName(jobKey.getName());
					job.setJobGroup(jobKey.getGroup());
					job.setDescription("触发器:" + trigger.getKey());
					Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
					job.setJobStatus(triggerState.name());
					if (trigger instanceof CronTrigger) {
						CronTrigger cronTrigger = (CronTrigger) trigger;
						String cronExpression = cronTrigger.getCronExpression();
						job.setCron(cronExpression);
					}
					jobList.add(job);
				}
			}
			return jobList;
		} catch (Exception e) {
			logger.error("获取系统所有任务出错！");
			throw new RuntimeException("获取系统所有任务出错！", e);
		}
	}

	@Override
	public List<TaskJob> getAllTaskJobRunning() {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
			List<TaskJob> jobList = new ArrayList<TaskJob>(executingJobs.size());
			for (JobExecutionContext executingJob : executingJobs) {
				TaskJob job = new TaskJob();
				JobDetail jobDetail = executingJob.getJobDetail();
				JobKey jobKey = jobDetail.getKey();
				Trigger trigger = executingJob.getTrigger();
				job.setJobName(jobKey.getName());
				job.setJobGroup(jobKey.getGroup());
				job.setDescription("触发器:" + trigger.getKey());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
				job.setJobStatus(triggerState.name());
				if (trigger instanceof CronTrigger) {
					CronTrigger cronTrigger = (CronTrigger) trigger;
					String cronExpression = cronTrigger.getCronExpression();
					job.setCron(cronExpression);
				}
				jobList.add(job);
			}
			return jobList;
		} catch (Exception e) {
			logger.error("获取系统所有正在运行任务出错！");
			throw new RuntimeException("获取系统所有正在运行任务出错！", e);
		}
	}

	@Override
	public void init() {
		// 这里获取任务信息数据
		List<TaskJob> jobList = taskJobService.selectList(new EntityWrapper<TaskJob>());
		logger.info("初始化加载数据库中配置的定时任务数："+(jobList!=null?jobList.size():0));
		for (TaskJob scheduleJob : jobList) {
			addTaskJob(scheduleJob);
		}
	}

}
